home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / access / nbtree / nbtscan.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  4.1 KB  |  169 lines

  1. /*
  2.  *  btscan.c -- manage scans on btrees.
  3.  *
  4.  *    Because we can be doing an index scan on a relation while we update
  5.  *    it, we need to avoid missing data that moves around in the index.
  6.  *    The routines and global variables in this file guarantee that all
  7.  *    scans in the local address space stay correctly positioned.  This
  8.  *    is all we need to worry about, since write locking guarantees that
  9.  *    no one else will be on the same page at the same time as we are.
  10.  *
  11.  *    The scheme is to manage a list of active scans in the current backend.
  12.  *    Whenever we add or remove records from an index, or whenever we
  13.  *    split a leaf page, we check the list of active scans to see if any
  14.  *    has been affected.  A scan is affected only if it is on the same
  15.  *    relation, and the same page, as the update.
  16.  */
  17.  
  18. #include "tmp/c.h"
  19. #include "tmp/postgres.h"
  20.  
  21. #include "storage/bufmgr.h"
  22. #include "storage/bufpage.h"
  23. #include "storage/page.h"
  24.  
  25. #include "utils/log.h"
  26. #include "utils/rel.h"
  27. #include "utils/excid.h"
  28.  
  29. #include "access/heapam.h"
  30. #include "access/genam.h"
  31. #include "access/sdir.h"
  32. #include "access/nbtree.h"
  33.  
  34. RcsId("$Header: /private/postgres/src/access/nbtree/RCS/nbtscan.c,v 1.4 1992/03/01 13:13:47 mao Exp $");
  35.  
  36. typedef struct BTScanListData {
  37.     IndexScanDesc        btsl_scan;
  38.     struct BTScanListData    *btsl_next;
  39. } BTScanListData;
  40.  
  41. typedef BTScanListData    *BTScanList;
  42.  
  43. static BTScanList    BTScans = (BTScanList) NULL;
  44.  
  45. /*
  46.  *  _bt_regscan() -- register a new scan.
  47.  */
  48.  
  49. void
  50. _bt_regscan(scan)
  51.     IndexScanDesc scan;
  52. {
  53.     BTScanList new_el;
  54.  
  55.     new_el = (BTScanList) palloc(sizeof(BTScanListData));
  56.     new_el->btsl_scan = scan;
  57.     new_el->btsl_next = BTScans;
  58.     BTScans = new_el;
  59. }
  60.  
  61. /*
  62.  *  _bt_dropscan() -- drop a scan from the scan list
  63.  */
  64.  
  65. void
  66. _bt_dropscan(scan)
  67.     IndexScanDesc scan;
  68. {
  69.     BTScanList chk, last;
  70.  
  71.     last = (BTScanList) NULL;
  72.     for (chk = BTScans;
  73.      chk != (BTScanList) NULL && chk->btsl_scan != scan;
  74.      chk = chk->btsl_next) {
  75.     last = chk;
  76.     }
  77.  
  78.     if (chk == (BTScanList) NULL)
  79.     elog(WARN, "btree scan list trashed; can't find 0x%lx", scan);
  80.  
  81.     if (last == (BTScanList) NULL)
  82.     BTScans = chk->btsl_next;
  83.     else
  84.     last->btsl_next = chk->btsl_next;
  85.  
  86. #ifdef PERFECT_MEM
  87.     pfree (chk);
  88. #endif /* PERFECT_MEM */
  89. }
  90.  
  91. void
  92. _bt_adjscans(rel, tid)
  93.     Relation rel;
  94.     ItemPointer tid;
  95. {
  96.     BTScanList l;
  97.     ObjectId relid, chkrelid;
  98.  
  99.     relid = rel->rd_id;
  100.     for (l = BTScans; l != (BTScanList) NULL; l = l->btsl_next) {
  101.     if (relid == l->btsl_scan->relation->rd_id)
  102.         _bt_scandel(l->btsl_scan, ItemPointerGetBlockNumber(tid),
  103.             ItemPointerGetOffsetNumber(tid, 0));
  104.     }
  105. }
  106.  
  107. void
  108. _bt_scandel(scan, blkno, offno)
  109.     IndexScanDesc scan;
  110.     BlockNumber blkno;
  111.     OffsetNumber offno;
  112. {
  113.     ItemPointer current;
  114.     Buffer buf;
  115.     BTScanOpaque so;
  116.  
  117.     if (!_bt_scantouched(scan, blkno, offno))
  118.     return;
  119.  
  120.     so = (BTScanOpaque) scan->opaque;
  121.     buf = so->btso_curbuf;
  122.  
  123.     current = &(scan->currentItemData);
  124.     if (ItemPointerIsValid(current)
  125.     && ItemPointerGetBlockNumber(current) == blkno
  126.     && ItemPointerGetOffsetNumber(current, 0) >= offno) {
  127.     _bt_step(scan, &buf, BackwardScanDirection);
  128.     so->btso_curbuf = buf;
  129.     }
  130.  
  131.     current = &(scan->currentMarkData);
  132.     if (ItemPointerIsValid(current)
  133.     && ItemPointerGetBlockNumber(current) == blkno
  134.     && ItemPointerGetOffsetNumber(current, 0) >= offno) {
  135.     ItemPointerData tmp;
  136.     tmp = *current;
  137.     *current = scan->currentItemData;
  138.     scan->currentItemData = tmp;
  139.     _bt_step(scan, &buf, BackwardScanDirection);
  140.     so->btso_mrkbuf = buf;
  141.     tmp = *current;
  142.     *current = scan->currentItemData;
  143.     scan->currentItemData = tmp;
  144.     }
  145. }
  146.  
  147. bool
  148. _bt_scantouched(scan, blkno, offno)
  149.     IndexScanDesc scan;
  150.     BlockNumber blkno;
  151.     OffsetNumber offno;
  152. {
  153.     ItemPointer current;
  154.  
  155.     current = &(scan->currentItemData);
  156.     if (ItemPointerIsValid(current)
  157.     && ItemPointerGetBlockNumber(current) == blkno
  158.     && ItemPointerGetOffsetNumber(current, 0) >= offno)
  159.     return (true);
  160.  
  161.     current = &(scan->currentMarkData);
  162.     if (ItemPointerIsValid(current)
  163.     && ItemPointerGetBlockNumber(current) == blkno
  164.     && ItemPointerGetOffsetNumber(current, 0) >= offno)
  165.     return (true);
  166.  
  167.     return (false);
  168. }
  169.